package org.hackystat.sensor.manual.devtime;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import javax.xml.datatype.XMLGregorianCalendar;
import org.fest.swing.fixture.FrameFixture;
import org.fest.swing.fixture.JButtonFixture;
import org.fest.swing.fixture.JLabelFixture;
import org.fest.swing.fixture.JTableFixture;
import org.fest.swing.fixture.JTextComponentFixture;
import org.hackystat.sensorbase.client.SensorBaseClient;
import org.hackystat.sensorbase.client.SensorBaseClientException;
import org.hackystat.sensorbase.resource.sensordata.jaxb.SensorData;
import org.hackystat.sensorbase.resource.sensordata.jaxb.SensorDataRef;
import org.hackystat.sensorshell.SensorShellProperties;
import org.hackystat.utilities.tstamp.Tstamp;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

/**
 * Test cases for HackyReporter.
 * @author Shaoxuan Zhang
 *
 */
public class TestHackyReporter {

  private FrameFixture hackyReportTester;
  private HackyReporter hackyReporter;

  private static final String testUser = "ManualReportTestUser@hackystat.org";
  private static final String testUserPassword = "ManualReportTestUser@hackystat.org";
  
  /** The test host. */
  protected static String host;
  /** The Sensorbase server used in these tests. */
  private static org.hackystat.sensorbase.server.Server sensorbaseServer;
  

  private SensorBaseClient client;

  /** 
   * Starts the servers going for these tests. 
   * @throws Exception If problems occur setting up the server. 
   */
  @BeforeClass public static void setupServer() throws Exception {
    sensorbaseServer = org.hackystat.sensorbase.server.Server.newTestInstance();
    sensorbaseServer.getLogger().setLevel(Level.FINEST);
    host = sensorbaseServer.getHostName();
    SensorBaseClient.registerUser(host, testUser);
  }
  
  /**
   * Initialize test helper.
   * @throws Exception if error occurs.
   */
  @Before public void setUp() throws Exception {
    SensorShellProperties prop = new SensorShellProperties(host, testUser, testUserPassword);
    client = new SensorBaseClient(host, testUser, testUserPassword);
    client.authenticate();
    client.deleteSensorData(testUser);
    hackyReporter = new HackyReporter(prop);
    hackyReportTester = new FrameFixture(hackyReporter);
    hackyReportTester.show();
  }
  
  /**
   * Clear up after each test.
   * @throws SensorBaseClientException error when clear up data.
   */
  @After public void clearUp() throws SensorBaseClientException {
    client.deleteSensorData(testUser);
    hackyReportTester.cleanUp();
  }

  /**
   * Test the ReportPanel.
   */
  @Test public void testReportPanel() {
    JTextComponentFixture endTimeField = hackyReportTester.textBox("endTime");
    JTextComponentFixture toolField = hackyReportTester.textBox("tool");
    JTextComponentFixture resourceField = hackyReportTester.textBox("resource");
    JButtonFixture submitButton = hackyReportTester.button("submit");
    JLabelFixture statusLabel = hackyReportTester.label("status");
    String ok = "Data sent.";
    //Check time validation
    String startTimeString = hackyReportTester.textBox("startTime").text();
    endTimeField.setText(startTimeString);
    submitButton.click();
    statusLabel.requireText("End time must be later than start time.");
    //Increase end time by 10 mintues
    Date date = new Date();
    date.setTime(date.getTime() + 500000);
    DateFormat timeFormat = hackyReporter.getReportPanel().getTimeFormat();
    String endTimeString = timeFormat.format(date);
    endTimeField.setText(endTimeString);
    //Check Tool validation
    toolField.deleteText();
    submitButton.click();
    statusLabel.requireText("Tool cannot be empty.");
    //Check resource and label validation 1. both empty
    toolField.setText("FEST-Tester");
    resourceField.deleteText();
    submitButton.click();
    statusLabel.requireText("Resource cannot be empty.");
    resourceField.setText("test/file");
    submitButton.click();
    statusLabel.requireText(ok);
    
    try {
      List<SensorDataRef> refs = client.getProjectSensorData(testUser, "Default", 
          Tstamp.makeTimestamp(timeFormat.parse(startTimeString).getTime()), 
          Tstamp.makeTimestamp(timeFormat.parse(endTimeString).getTime()), "DevTime", "FEST-Tester")
          .getSensorDataRef();
      assertEquals("Check data numbers.", 2, refs.size());
    }
    catch (SensorBaseClientException e) {
      fail("Fail to retrieve sensor data.");
    }
    catch (ParseException e) {
      fail("Date string parse fail.");
    }
  }
  
  /**
   * Test the history panel.
   * @throws SensorBaseClientException when error.
   */
  @Test public void testHistoryPanel() throws SensorBaseClientException {
    client.authenticate();
    XMLGregorianCalendar runTime = Tstamp.makeTimestamp();
    XMLGregorianCalendar time1 = Tstamp.incrementSeconds(runTime, 10);
    XMLGregorianCalendar time2 = Tstamp.incrementSeconds(runTime, 20);
    XMLGregorianCalendar time3 = Tstamp.incrementSeconds(runTime, 30);
    XMLGregorianCalendar time4 = Tstamp.incrementSeconds(runTime, 40);
    XMLGregorianCalendar time5 = Tstamp.incrementSeconds(runTime, 50);
    XMLGregorianCalendar time6 = Tstamp.incrementSeconds(runTime, 15);
    //two data with tool1, testfile1
    SensorData data1 = new SensorData();
    data1.setOwner(testUser);
    data1.setResource("TestFile1");
    data1.setSensorDataType(SensorManager.SDT);
    data1.setTool("Tool1");
    data1.addProperty(SensorManager.SELF_REPORT_PROPERTY, "true");
    data1.setRuntime(runTime);
    data1.setTimestamp(time1);
    client.putSensorData(data1);
    data1.setTimestamp(time2);
    client.putSensorData(data1);

    //three data with tool2, testfile2
    SensorData data2 = new SensorData();
    data2.setOwner(testUser);
    data2.setResource("TestFile2");
    data2.setSensorDataType(SensorManager.SDT);
    data2.setTool("Tool2");
    data2.addProperty(SensorManager.SELF_REPORT_PROPERTY, "true");
    data2.setRuntime(runTime);
    data2.setTimestamp(time3);
    client.putSensorData(data2);
    data2.setTimestamp(time4);
    client.putSensorData(data2);
    data2.setTimestamp(time5);
    client.putSensorData(data2);

    //one non-manual reported data
    SensorData data3 = new SensorData();
    data3.setOwner(testUser);
    data3.setResource("TestFile3");
    data3.setSensorDataType(SensorManager.SDT);
    data3.setTool("Tool3");
    data3.addProperty("false", "data");
    data3.setTimestamp(time6);
    client.putSensorData(data3);
    
    String refresh = "refresh";
    String tool = "tool";
    
    hackyReportTester.tabbedPane().selectTab("History");
    hackyReportTester.textBox(tool).setText("");
    hackyReportTester.button(refresh).click();
    assertEquals("5 data in total.", 5, hackyReportTester.table().rowCount());

    hackyReportTester.textBox(tool).setText("Tool1");
    hackyReportTester.button(refresh).click();
    assertEquals("2 data of tool1.", 2, hackyReportTester.table().rowCount());
    
    JTableFixture table = hackyReportTester.table();  
    table.target.selectAll();
    hackyReportTester.button("delete").click();
    assertEquals("no data of tool1 now.", 0, hackyReportTester.table().rowCount());

  }
}
